package jp.sourceforge.akjrcp.text_douga.item;

import java.math.BigDecimal;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import jp.sourceforge.akjrcp.text_douga.DougaPreference;
import jp.sourceforge.akjrcp.text_douga.DougaSystem;
import jp.sourceforge.akjrcp.text_douga.ItemData;

public abstract class AbstractItem implements ItemData{
	public static Log log=LogFactory.getLog(AbstractItem.class);
	
	public AbstractItem(AbstractItem base){
		this.align=base.align;
		this.valign=base.valign;
		this.startTime=base.startTime;
		this.duration=base.duration;
		this.fadeInTime=base.fadeInTime;
		this.fadeOutTime=base.fadeOutTime;
		this.transparent=base.transparent;
		
		this.x=base.x;
		this.y=base.y;
		this.z=base.z;
		this.width=base.width;
		this.height=base.height;
		
		this.marginLeft=base.marginLeft;
		this.marginRight=base.marginRight;
		this.marginTop=base.marginTop;
		this.marginBottom=base.marginBottom;
		
		this.keepAspect=base.keepAspect;
		this.moveX=base.moveX;
		this.moveY=base.moveY;
		this.moveWidth=base.moveWidth;
		this.moveHeight=base.moveHeight;
		this.shearX=base.shearX;
		this.shearY=base.shearY;
		this.rotate=base.rotate;
		this.moveRotate=base.moveRotate;
	}
	public AbstractItem(){
		super();
	}
	protected int align;
	protected int valign;
	protected double startTime;
	protected double duration = 1.0;
	protected  double fadeInTime = 0.2;
	protected  double fadeOutTime = 0.2;
	protected  float transparent = 1.0f;

	protected int x;
	protected int y;
	
	protected int width;
	protected int height;
	
	protected int z;
	
	protected int marginLeft=16;
	protected int marginRight=16;
	protected int marginTop=16;
	protected int marginBottom=16;
	
	protected boolean keepAspect=true;
	protected double moveX;
	protected double moveY;
	protected double moveWidth;
	protected double moveHeight;
	
	protected double shearX;
	protected double shearY;
	protected int rotate;
	protected int moveRotate;
	protected double getFrameTime(int frame,double fps){
		if(frame==1){
			return 0;
		}
		return (frame-1)/fps;
	}
	public double getMoveX() {
		return moveX;
	}

	public void setMoveX(double moveX) {
		this.moveX = moveX;
	}

	public double getMoveY() {
		return moveY;
	}

	public void setMoveY(double moveY) {
		this.moveY = moveY;
	}

	public int getMovedX(DougaPreference preference,double currentTime){
		
		if(moveX==0){
			return 0;
		}
		
		double diffTime=currentTime-getStartTime();
		return new BigDecimal(""+moveX).multiply(new BigDecimal(""+diffTime)).intValue();
	}
	
	public int getMovedRotate(DougaPreference preference,double currentTime){
		
		if(moveRotate==0){
			return rotate;
		}
		
		double diffTime=currentTime-getStartTime();
		return new BigDecimal(""+moveRotate).multiply(new BigDecimal(""+diffTime)).intValue()%360;
	}
	
public int getMovedWidth(DougaPreference preference,double currentTime){
		
		if(moveHeight==0){
			return 0;
		}
		
		double diffTime=currentTime-getStartTime();
		return new BigDecimal(""+moveHeight).multiply(new BigDecimal(""+diffTime)).intValue();
	}

public int getMovedHeight(DougaPreference preference,double currentTime){
	
	if(moveWidth==0){
		return 0;
	}
	
	double diffTime=currentTime-getStartTime();
	return new BigDecimal(""+moveWidth).multiply(new BigDecimal(""+diffTime)).intValue();
}
	
public int getMovedY(DougaPreference preference,double currentTime){
		
		if(moveY==0){
			return 0;
		}
		
		double diffTime=currentTime-getStartTime();
		return new BigDecimal(""+moveY).multiply(new BigDecimal(""+diffTime)).intValue();
	}
	/*
	public int getMovedX(DougaPreference preference,int frame){
		
		if(moveX==0){
			return 0;
		}
		
		int startF=1;//frame is start 1;
		if(getStartTime()>0){
			startF=Math.max(1,(int) (getStartTime()*preference.getFps()));
			//System.out.println("startF:"+startF);
		}else{
			startF=1;//min is 1
		}
		return (int)(moveX/preference.getFps())*(frame-startF);
	}
	
	public int getMovedY(DougaPreference preference,int frame){
		if(moveY==0){
			return 0;
		}
		int startF=1;
		if(getStartTime()>0){
			startF=Math.max(1,new BigDecimal(""+getStartTime()).multiply(new BigDecimal(""+preference.getFps())).intValue());
		}else{
			startF=1;
		}
		if(frame==1){
			System.out.println("startF="+startF);
		}
		return new BigDecimal(""+moveY).multiply(new BigDecimal(frame-startF)).intValue();
	}*/

	/**
	 * check overwrap 
	 * maybe for textitem
	 */
	public static boolean isOverwrapTime(AbstractItem item1,AbstractItem item2){
		if(item1.getDuration()==DougaSystem.FOREEVER|| item2.getDuration()==DougaSystem.FOREEVER){
			return true;
		}
		
		if(item1.getStartTime()>=item2.getStartTime() && item1.getStartTime()<item2.getStartTime()+item2.getDuration()){
			
			return true;
		}
		//same end ignore it.
		if(item1.getStartTime()+item1.getDuration()>item2.getStartTime() && item1.getStartTime()+item1.getDuration()<=item2.getStartTime()+item2.getDuration()){
			
			return true;
		}
		
		return false;
	}
	
	public void setBounds(int x,int y,int width,int height){
		setX(x);
		setY(y);
		setWidth(width);
		setHeight(height);
	}
	public String  toString(){
		return "startTime="+startTime+" duration="+duration+" fadeInTime="+fadeInTime+" fadeOutTime="+fadeOutTime+" transparent="+transparent+" x="+x
				+" y="+y+" width="+width+" height="+height+" z="+z+" align="+align+ " valign="+valign+" keepAspect="+keepAspect;
	}
	public int getZ() {
		// small is firster
		return z;
	}

	public float getFrameTransparent(DougaPreference preference,double time) {
		
		if(duration==DougaSystem.FOREEVER){
			//return 1;//draw alltime
			return transparent;
		}
		if(fadeInTime==0 && fadeOutTime==0){
			//no fadeout
			return transparent;
		}
		
		double drawTransparent=transparent;
		double t=time-startTime;
		if(t<=0 || t>=duration){//initial or after
			if(t<0 || t>duration)
				log.warn("invalid t:"+t);
			if(fadeInTime==0 &&t<=0){
				
				return transparent;
			}else if(fadeOutTime==0 && t>=duration){//need it?
				return transparent;
				}
			;
			if(t==0 && (double)1/preference.getFps()>fadeInTime){//for case fps 1
				return (float)drawTransparent;
			}
			return 0.03f;//if don't draw useless 
		}
		if(t>0 && t<fadeInTime){//fade in
			drawTransparent=t/fadeInTime*transparent;
			if(drawTransparent<0 || drawTransparent>1){
				log.warn("invalid fadeIn:"+"time="+t+","+drawTransparent);
			}
		}else if(t>duration-fadeOutTime){//fade out
			drawTransparent=(duration-t)/fadeOutTime*transparent;
			if(drawTransparent<0 || drawTransparent>1){
				log.warn("invalid fadeOut:"+"time="+t+","+drawTransparent);
			}
		}
		
		return (float)drawTransparent;
	}

	public float getTransparent() {
		return transparent;
	}

	public void setTransparent(float transparent) {
		this.transparent = transparent;
	}

	public int getAlign() {
		return align;
	}

	public void setAlign(int align) {
		this.align = align;
	}

	public double getDuration() {
		return duration;
	}

	public void setDuration(double duration) {
		this.duration = duration;
	}


	public int getHeight() {
		return height;
	}

	public void setHeight(int height) {
		this.height = height;
	}

	public double getStartTime() {
		return startTime;
	}

	public void setStartTime(double startTime) {
		this.startTime = startTime;
	}

	public int getValign() {
		return valign;
	}

	public void setValign(int valign) {
		this.valign = valign;
	}

	public int getWidth() {
		return width;
	}

	public void setWidth(int width) {
		this.width = width;
	}

	public int getX() {
		return x;
	}

	public void setX(int x) {
		this.x = x;
	}

	public int getY() {
		return y;
	}

	public void setY(int y) {
		this.y = y;
	}

	public void setZ(int z) {
		this.z = z;
	}

	public double getFadeInTime() {
		return fadeInTime;
	}

	public void setFadeInTime(double fadeInTime) {
		this.fadeInTime = fadeInTime;
	}

	public double getFadeOutTime() {
		return fadeOutTime;
	}

	public void setFadeOutTime(double fadeOutTime) {
		this.fadeOutTime = fadeOutTime;
	}
	
	public boolean isKeepAspect() {
		return keepAspect;
	}
	public void setKeepAspect(boolean keepAspect) {
		this.keepAspect = keepAspect;
	}
	
	public double getLastTime() {
		if(duration!=DougaSystem.FOREEVER){
			return startTime+duration;
		}
		return 0;
	}
	
	public boolean isInFrame(DougaPreference preference,int frame){
		
		double frameTime=(double)(frame-1)/preference.getFps();//to change start 0
		if(frameTime>=startTime && frameTime<startTime+duration){
			log.trace("intime:"+frameTime+" start="+startTime+" end="+(startTime+duration));
			return true;
			}
		
		return false;
	}
	public double getMoveWidth() {
		return moveWidth;
	}
	public void setMoveWidth(double moveWidth) {
		this.moveWidth = moveWidth;
	}
	public double getMoveHeight() {
		return moveHeight;
	}
	public void setMoveHeight(double moveHeight) {
		this.moveHeight = moveHeight;
	}

	public double getShearX() {
		return shearX;
	}
	public void setShearX(double shearX) {
		this.shearX = shearX;
	}
	public double getShearY() {
		return shearY;
	}
	public void setShearY(double shearY) {
		this.shearY = shearY;
	}
	public int getRotate() {
		return rotate;
	}
	public void setRotate(int rotate) {
		this.rotate = rotate;
	}
	public int getMoveRotate() {
		return moveRotate;
	}
	public void setMoveRotate(int move_rorate) {
		this.moveRotate = move_rorate;
	}

}
